package at.technikum_wien.embsys.aat.PriscillaCore.component;

import java.util.List;

import at.technikum_wien.embsys.aat.PriscillaCore.enums.EnoceanComponentType;
import at.technikum_wien.embsys.aat.PriscillaCore.telegram.Telegram;



/**
 * 
 * EEP_07_13_02 component class - environmental applications
 *
 * Type: environmental applications - sun intensity
 * Sun intensity: 0-150000lx
 * 
 * @author B. Aigner
 * 
 */
public class EEP_07_13_02 implements EnoceanComponent {
	
	Telegram telegram;
	List<?> eventListener;
	
	int sunWest = -300;
	int sunSouth = -300;
	int sunEast = -300;
	
	int identifier;
	
	EnoceanComponentType enoceanComponentType = EnoceanComponentType.EEP_07_13_02;
	boolean telegramCreation = false;
	
	int sun_west_temp = telegram.getData3();
	int sun_west_max = 150000;
	int sun_west_min = 0;
	int sun_west_value_max = 255;
	int sun_west_value_min = 0;
	
	int sun_south_temp = telegram.getData2();
	int sun_south_max = 150000;
	int sun_south_min = 0;
	int sun_south_value_max = 255;
	int sun_south_value_min = 0;
	
	int sun_east_temp = telegram.getData1();
	int sun_east_max = 150000;
	int sun_east_min = 0;
	int sun_east_value_max = 255;
	int sun_east_value_min = 0;
	
	double multiplier;

	/**
	 * This constructor is used for received packets.
	 * It will parse the telegram and set the corresponding members.
	 * 
	 * @param telegram Received Telegram
	 * @param listener Event subscriber list
	 */
	public EEP_07_13_02(Telegram telegram, List<?> listener) {
		super();
		this.telegram = telegram;
		this.eventListener = listener;
		

		identifier = (telegram.getData0() & 0xF0) / 16;

		multiplier = (sun_west_max - sun_west_min) / (sun_west_value_max - sun_west_value_min);

		if(multiplier >= 0) {
			this.sunWest = (int)(multiplier * sun_west_temp + sun_west_max);
		} else {
			this.sunWest = (int)(multiplier * sun_west_temp + sun_west_min);
		}


		multiplier = (sun_south_max - sun_south_min) / (sun_south_value_max - sun_south_value_min);

		if(multiplier >= 0) {
			this.sunSouth = (int)(multiplier * sun_south_temp + sun_south_max);
		} else {
			this.sunSouth = (int)(multiplier * sun_south_temp + sun_south_min);
		}


		multiplier = (sun_east_max - sun_east_min) / (sun_east_value_max - sun_east_value_min);

		if(multiplier >= 0) {
			this.sunEast = (int)(multiplier * sun_east_temp + sun_east_max);
		} else {
			this.sunEast = (int)(multiplier * sun_east_temp + sun_east_min);
		}
		fireFrame();
	}

	/**
	 * Fire all associated events
	 */
	void fireFrame() {
		//TODO: WeatherStation Event
		/*
		Iterator listen = eventListener.iterator();
		final FrameEventFan frameEventFan = new FrameEventFan(this, telegram.getDeviceID(), this.fanspeed, this.fantype );
		while (listen.hasNext()) {
			((LinkListener) listen.next()).frameReceived_Fan(frameEventFan);
		}
		*/
	}

	/**
	 * Void constructor. It is used to create a new telegram for sending
	 */
	public EEP_07_13_02() {
		super();
		telegram = new Telegram();
		telegramCreation = true;
	}

	/**
	 * This constructor is used to create a telegram (the device id is given as parameter)
	 * @param deviceID Full device ID
	 */
	public EEP_07_13_02(String deviceID) {
		super();
		telegram = new Telegram();
		telegram.setDeviceID(deviceID);
		telegramCreation = true;
	}
	
	boolean checkBit(int value, int bitNr) {
		return (value & (1 << bitNr)) != 0;
	}
	
	int setBit(int value, int bitNr) {
		return value | (1<<bitNr);
	}
	
	int clrBit(int value, int bitNr) {
		return value & (~(1<<bitNr));
	}
	
	@Override
	public String getDeviceID() {
		return telegram.getDeviceID();
	}
	@Override
	public String getORG() {
		return telegram.getxORG();
	}
	@Override
	public EnoceanComponentType getType() {
		return enoceanComponentType;
	}

	@Override
	public void setDeviceID(String deviceID) {
		telegram.setDeviceID(deviceID);
	}

	/**
	 * Creates a new telegram from the component
	 * 
	 * This method creates a new telegram (if the component is initialized with
	 * a constructor without a telegram as parameter) or returns the saved telegram.
	 * The new telegram is built up from the members in this class (in this case environmental data). 
	 * @return Created telegram
	 */
	public Telegram getTelegram() {
		if(telegramCreation == true) {
			multiplier = (sun_east_max - sun_east_min) / (sun_east_value_max - sun_east_value_min);
			if(multiplier < 0) {
				sun_east_temp = (int)((this.sunEast - sun_east_max) / multiplier);
			} else {
				sun_east_temp = (int)((this.sunEast - sun_east_min) / multiplier);
			}
			telegram.setData1(sun_east_temp);
			
			multiplier = (sun_south_max - sun_south_min) / (sun_south_value_max - sun_south_value_min);
			if(multiplier < 0) {
				sun_south_temp = (int)((this.sunSouth - sun_south_max) / multiplier);
			} else {
				sun_south_temp = (int)((this.sunSouth - sun_south_min) / multiplier);
			}
			telegram.setData2(sun_south_temp);
			
			multiplier = (sun_west_max - sun_west_min) / (sun_west_value_max - sun_west_value_min);
			if(multiplier < 0) {
				sun_west_temp = (int)((this.sunWest - sun_west_max) / multiplier);
			} else {
				sun_west_temp = (int)((this.sunWest - sun_west_min) / multiplier);
			}
			telegram.setData3(sun_west_temp);
			
		}
		return telegram;
	}

	public int getSunWest() {
		return sunWest;
	}

	public int getSunSouth() {
		return sunSouth;
	}

	public int getSunEast() {
		return sunEast;
	}

	public int getIdentifier() {
		return identifier;
	}
	
	public void setSunSouth(int sunSouth) {
		if(sunSouth > sun_south_max) return;
		if(sunSouth < sun_south_min) return;
		this.sunSouth = sunSouth;
	}
	
	public void setSunWest(int sunWest) {
		if(sunWest > sun_west_max) return;
		if(sunWest < sun_west_min) return;
		this.sunWest = sunWest;
	}
	
	public void setSunEast(int sunEast) {
		if(sunEast > sun_east_max) return;
		if(sunEast < sun_east_min) return;
		this.sunEast = sunEast;
	}
}
